using System;
using System.Collections.Generic;

namespace GameKit.Core
{
    public class EntityEvent
    {
        private Dictionary<string, Delegate> EventDict { get; set; } = new();

        public void Register(string key, Action listener)
        {
            if (EventDict.ContainsKey(key))
            {
                EventDict[key] = Delegate.Combine(EventDict[key], listener);
            }
            else
            {
                EventDict[key] = listener;
            }
        }

        public void Register<T>(string key, Action<T> listener)
        {
            if (EventDict.ContainsKey(key))
            {
                EventDict[key] = Delegate.Combine(EventDict[key], listener);
            }
            else
            {
                EventDict[key] = listener;
            }
        }

        public void Unregister(string key, Action listener)
        {
            if (!EventDict.ContainsKey(key)) return;

            EventDict[key] = Delegate.Remove(EventDict[key], listener);
            if (EventDict[key] == null)
            {
                EventDict.Remove(key);
            }
        }

        public void Unregister<T>(string key, Action<T> listener)
        {
            if (!EventDict.ContainsKey(key)) return;

            EventDict[key] = Delegate.Remove(EventDict[key], listener);
            if (EventDict[key] == null)
            {
                EventDict.Remove(key);
            }
        }

        public void Unregister(string key)
        {
            if (EventDict.ContainsKey(key))
            {
                EventDict.Remove(key);
            }
        }

        public void Broadcast<T>(string key, T message)
        {
            if (!EventDict.TryGetValue(key, out var value)) return;
            var listener = value as Action<T>;
            listener?.Invoke(message);
        }

        public void Broadcast(string key)
        {
            if (!EventDict.TryGetValue(key, out var value)) return;
            var listener = value as Action;
            listener?.Invoke();
        }

        public void ClearEvents()
        {
            EventDict.Clear();
        }
    }
}